int32						i32Status = CS_SUCCESS;
uInt32						i;
TCHAR						szFileName[MAX_PATH];
int64						i64Depth = 0;
void*						pBuffer = NULL;
float*						pVBuffer = NULL;
uInt32						u32Mode;
CSHANDLE					hSystem = 0;
IN_PARAMS_TRANSFERDATA		InData = {0};
OUT_PARAMS_TRANSFERDATA		OutData = {0};
CSSYSTEMINFO				CsSysInfo = {0};
CSAPPLICATIONDATA			CsAppData = {0};
FileHeaderStruct			stHeader = {0};
CSACQUISITIONCONFIG			CsAcqCfg = {0};
CSCHANNELCONFIG				CsChanCfg = {0};
LPCTSTR						szIniFile = _T("GageAcquisition.ini");
uInt32						u32ChannelIndexIncrement;

int GageInitializeC()
{
	/*
		Initializes the CompuScope boards found in the system. If the
		system is not found a message with the error code will appear.
		Otherwise i32Status will contain the number of systems found.
	*/
		i32Status = CsInitialize();

		if (CS_FAILED(i32Status))
		{
			DisplayErrorString(i32Status);
			return (-1);
		}

	/*
		Get System. This sample program only supports one system. If
		2 systems or more are found, the first system that is found
		will be the system that will be used. hSystem will hold a unique
		system identifier that is used when referencing the system.
	*/
		i32Status = CsGetSystem(&hSystem, 0, 0, 0, 0);

		if (CS_FAILED(i32Status))
		{
			DisplayErrorString(i32Status);
			return (-1);
		}
	/*
		Get System information. The u32Size field must be filled in
		 prior to calling CsGetSystemInfo
	*/
		CsSysInfo.u32Size = sizeof(CSSYSTEMINFO);
		i32Status = CsGetSystemInfo(hSystem, &CsSysInfo);

	/*
		Display the system name from the driver
	*/
		_ftprintf(stdout, _T("\nBoard Name: %s"), CsSysInfo.strBoardName);

	/*
		Complex trigger needs to have at least two triggers configured.
		Third parameter of the ConfigureSystem is the TriggerCount to be configured.
	*/
		i32Status = CsAs_ConfigureSystem(hSystem, (int)CsSysInfo.u32ChannelCount, (int)CsSysInfo.u32TriggerMachineCount, (LPCTSTR)szIniFile, &u32Mode);

		if (CS_FAILED(i32Status))
		{
			if (CS_INVALID_FILENAME == i32Status)
			{
	/*
				Display message but continue on using defaults.
	*/
				_ftprintf(stdout, _T("\nCannot find %s - using default parameters."), szIniFile);
			}
			else
			{
	/*
				Otherwise the call failed.  If the call did fail we should free the CompuScope
				system so it's available for another application
	*/
				DisplayErrorString(i32Status);
				CsFreeSystem(hSystem);
				return(-1);
			}
		}
	/*
		If the return value is greater than  1, then either the application,
		acquisition, some of the Channel and / or some of the Trigger sections
		were missing from the ini file and the default parameters were used.
	*/
		if (CS_USING_DEFAULT_ACQ_DATA & i32Status)
			_ftprintf(stdout, _T("\nNo ini entry for acquisition. Using defaults."));

		if (CS_USING_DEFAULT_CHANNEL_DATA & i32Status)
			_ftprintf(stdout, _T("\nNo ini entry for one or more Channels. Using defaults for missing items."));

		if (CS_USING_DEFAULT_TRIGGER_DATA & i32Status)
			_ftprintf(stdout, _T("\nNo ini entry for one or more Triggers. Using defaults for missing items."));

		i32Status = CsAs_LoadConfiguration(hSystem, szIniFile, APPLICATION_DATA, &CsAppData);

		if (CS_FAILED(i32Status))
		{
			if (CS_INVALID_FILENAME == i32Status)
				_ftprintf(stdout, _T("\nUsing default application parameters."));
			else
			{
				DisplayErrorString(i32Status);
				CsFreeSystem(hSystem);
				return -1;
			}
		}
		else if (CS_USING_DEFAULT_APP_DATA & i32Status)
		{
	/*
			If the return value is CS_USING_DEFAULT_APP_DATA (defined in ConfigSystem.h)
			then there was no entry in the ini file for Application and we will use
			the application default values, which were set in CsAs_LoadConfiguration.
	*/
			_ftprintf(stdout, _T("\nNo ini entry for application data. Using defaults"));
		}

	/*
		Commit the values to the driver.  This is where the values get sent to the
		hardware.  Any invalid parameters will be caught here and an error returned.
	*/
		i32Status = CsDo(hSystem, ACTION_COMMIT);
		if (CS_FAILED(i32Status))
		{
			DisplayErrorString(i32Status);
			CsFreeSystem(hSystem);
			return (-1);
		}
	/*
		Get the current sample size, resolution and offset parameters from the driver
		by calling CsGet for the ACQUISTIONCONFIG structure. These values are used
		when saving the file.
	*/
		CsAcqCfg.u32Size = sizeof(CsAcqCfg);
		i32Status = CsGet(hSystem, CS_ACQUISITION, CS_ACQUISITION_CONFIGURATION, &CsAcqCfg);
		if (CS_FAILED(i32Status))
		{
			DisplayErrorString(i32Status);
			CsFreeSystem(hSystem);
			return (-1);
		}
	/*
		We need to allocate a buffer
		for transferring the data
	*/
		pBuffer  = VirtualAlloc(NULL, (size_t)(CsAppData.i64TransferLength * CsAcqCfg.u32SampleSize), MEM_COMMIT, PAGE_READWRITE);
		if (NULL == pBuffer)
		{
			_ftprintf (stderr, _T("\nUnable to allocate memory\n"));
			CsFreeSystem(hSystem);
			return (-1);
		}

		if (TYPE_FLOAT == CsAppData.i32SaveFormat)
		{
	/*
			Allocate another buffer to pass the data that is going to be converted
			into voltages
	*/
			pVBuffer  = (float *)VirtualAlloc(NULL, (size_t)(CsAppData.i64TransferLength * sizeof(float)), MEM_COMMIT, PAGE_READWRITE);
			if (NULL == pVBuffer)
			{
				_ftprintf (stderr, _T("\nUnable to allocate memory\n"));
				CsFreeSystem(hSystem);
				VirtualFree(pBuffer, 0, MEM_RELEASE);
				return (-1);
			}
		}
}


int GageAcquireC()
{
	/*
		Start the data Acquisition
	*/
		i32Status = CsDo(hSystem, ACTION_START);
		if (CS_FAILED(i32Status))
		{
			DisplayErrorString(i32Status);
			CsFreeSystem(hSystem);
			return (-1);
		}

		if (!DataCaptureComplete(hSystem))
		{
			CsFreeSystem(hSystem);
			return (-1);
		}

	/*
		Acquisition is now complete.
		Fill in the InData structure for transferring the data
	*/
	/*
		Non multiple record captures should have the segment set to 1.
		InData.u32Mode refers to the transfer mode. Regular transfer is 0
	*/
		InData.u32Segment = 1;
		InData.u32Mode = TxMODE_DEFAULT;
		InData.i64StartAddress = CsAppData.i64TransferStartPosition;
		InData.i64Length =  CsAppData.i64TransferLength;
		InData.pDataBuffer = pBuffer;

		u32ChannelIndexIncrement = CsAs_CalculateChannelIndexIncrement(&CsAcqCfg, &CsSysInfo );

		for	(i = 1; i <= CsSysInfo.u32ChannelCount; i += u32ChannelIndexIncrement)
		{
	/*
			Variable that will contain either raw data or data in Volts depending on requested format
	*/
			void* pSrcBuffer = NULL;

			ZeroMemory(pBuffer,(size_t)(CsAppData.i64TransferLength * CsAcqCfg.u32SampleSize));
			InData.u16Channel = (uInt16)i;
	/*
			Transfer the captured data
	*/
			i32Status = CsTransfer(hSystem, &InData, &OutData);
			if (CS_FAILED(i32Status))
			{
				DisplayErrorString(i32Status);
				if (NULL != pBuffer)
					VirtualFree(pBuffer, 0, MEM_RELEASE);
				if (NULL != pVBuffer)
					VirtualFree(pVBuffer, 0, MEM_RELEASE);
				CsFreeSystem(hSystem);
				return (-1);
			}
	/*
			Note: to optimize the transfer loop, everything from
			this point on in the loop could be moved out and done
			after all the channels are transferred.
	*/

	/*
			Assign a file name for each channel that we want to save
	*/
			_stprintf(szFileName, _T("%s_CH%d.dat"), CsAppData.lpszSaveFileName, i);

	/*
			Gather up the information needed for the volt conversion and/or file header
	*/
			CsChanCfg.u32Size = sizeof(CSCHANNELCONFIG);
			CsChanCfg.u32ChannelIndex = i;
			CsGet(hSystem, CS_CHANNEL, CS_ACQUISITION_CONFIGURATION, &CsChanCfg);

			if (TYPE_FLOAT == CsAppData.i32SaveFormat)
			{
	/*
				Call the ConvertToVolts function. This function will convert the raw
				data to voltages. We pass the actual length, which will be converted
				from 0 to actual length.  Any invalid samples at the beginning are
				handled in the SaveFile routine.
	*/
				i64Depth = OutData.i64ActualLength;

				i32Status = CsAs_ConvertToVolts(i64Depth, CsChanCfg.u32InputRange, CsAcqCfg.u32SampleSize,
												CsAcqCfg.i32SampleOffset, CsAcqCfg.i32SampleRes,
												CsChanCfg.i32DcOffset, pBuffer, pVBuffer);

				if (CS_FAILED(i32Status))
				{
					DisplayErrorString(i32Status);
					continue;
				}

				pSrcBuffer = pVBuffer;
			}
			else
			{
				pSrcBuffer = pBuffer;
			}
	/*
			The driver may have had to change the start address and length
			due to alignment issues, so we'll get the actual start and length
			from the driver.
	*/

			stHeader.i64Start = OutData.i64ActualStart;
			stHeader.i64Length = OutData.i64ActualLength;
			stHeader.u32SampleSize = CsAcqCfg.u32SampleSize;
			stHeader.i32SampleRes = CsAcqCfg.i32SampleRes;
			stHeader.i32SampleOffset = CsAcqCfg.i32SampleOffset;
			stHeader.u32InputRange = CsChanCfg.u32InputRange;
			stHeader.i32DcOffset = CsChanCfg.i32DcOffset;
			stHeader.u32SegmentCount = CsAcqCfg.u32SegmentCount;
			stHeader.u32SegmentNumber = InData.u32Segment;
			stHeader.dTimeStamp = NO_TIME_STAMP_VALUE;


			i32Status = (int32)CsAs_SaveFile(szFileName, pSrcBuffer, CsAppData.i32SaveFormat, &stHeader);
			if ( 0 > i32Status )
			{
				if (CS_MISC_ERROR == i32Status)
				{
					_ftprintf(stderr, _T("\n"));
					_ftprintf(stderr, CsAs_GetLastFileError());
				}
				else
				{
					DisplayErrorString(i32Status);
				}
				continue;
			}
		}

	/*
		Free any buffers that have been allocated
	*/
		if ( NULL != pVBuffer )
		{
			VirtualFree(pVBuffer, 0, MEM_RELEASE);
			pVBuffer = NULL;
		}

		if ( NULL != pBuffer)
		{
			VirtualFree(pBuffer, 0, MEM_RELEASE);
			pBuffer = NULL;
		}
}

int GageCloseRessourceC()
{
	/*
		Free the CompuScope system and any resources it's been using
	*/
		i32Status = CsFreeSystem(hSystem);

		DisplayFinishString();
		return 0;
}
